<?php
	//Include the utf-8 string processing functions
	require_once(dirname(__FILE__).'/utf8.php');

	/**
	* Recursively use stripslashes on an array or a value
	*
	* @param mixed $value The array or value to perform stripslashes on
	*
	* @return mixed The array or value which was stripslashed
	*/
	function stripslashes_deep($value)
	{
		$value = is_array($value) ? array_map('stripslashes_deep', $value) : stripslashes($value);
		return $value;
	}

	/**
	* Write a string to a file
	*
	* @param string $str The string to write to the file
	* @param string $filename The full path to the file to write to
	*
	* @return boolean True if write to the file succeeds
	*/

	function str_to_file($str, $filename)
	{
		// If its not a file, stop
		if (!is_file($filename)) {
			return false;
		}

		// If its not writeable stop
		if (!is_writeable($filename)) {
			return false;
		}

		// If we arn't really writing anything just touch the file
		if (empty($str)) {
			touch($filename);
			return true;
		}

		// Write the contents of str to the file
		$fp = fopen($filename, 'w+');
		if ($fp) {
			fwrite($fp, $str);
			fclose($fp);
			return true;
		} else {
			return false;
		}

		// We should never get to here
		return false;
	}

	/**
	* Trim a string down to size and add ellipses if it is longer then required
	*
	* @param string $str The string to examine
	* @param integer $len The threshold to trim the string at
	*
	* @return string returns the ellipsized string
	*/
	function ellipsize($str, $len=72)
	{
		if ($GLOBALS['charset'] == 'utf-8') {
			if (utf8_strlen($str) <= $len) {
				return $str;
			} else {
				return utf8_substr($str, 0, $len-4).' ...';
			}
		} else {
			if (strlen($str) <= $len) {
				return $str;
			} else {
				return substr($str, 0, $len-4).' ...';
			}
		}
	}

	/**
	* Replace spaces and dashs in a url with other characters
	*
	* @param string $val the str to make safe
	*
	* @return string the safe string
	*/
	function makeUrlSafe($val)
	{
		$targets = array(' ', '/');
		$replaces = array('-', '{47}');
		return urlencode(str_replace($targets, $replaces, $val));
	}

	/**
	* Confirm the email address
	*
	* @param string $email The email to check the format of
	*
	* @return boolean True if the email is a valid format, false otherwise
	*/
	function is_email_address($email)
	{
		// If the email is empty it can't be valid
		if (empty($email)) {
			return false;
		}

		// If the email doesnt have exactle 1 @ it isnt valid
		if (substr_count($email, '@') != 1) {
			return false;
		}

		$matches = array();
		$local_matches = array();
		preg_match(':^([^@]+)@([a-zA-Z0-9\-][a-zA-Z0-9\-\.]{0,254})$:', $email, $matches);

		if (count($matches) != 3) {
			return false;
		}

		$local = $matches[1];
		$domain = $matches[2];

		// If the local part has a space but isnt inside quotes its invalid
		if (strpos($local, ' ') && (substr($local, 0, 1) != '"' || substr($local, -1, 1) != '"')) {
			return false;
		}

		// If there are not exactly 0 and 2 quotes
		if (substr_count($local, '"') != 0 && substr_count($local, '"') != 2) {
			return false;
		}

		// if the local part starts or ends with a dot (.)
		if (substr($local, 0, 1) == '.' || substr($local, -1, 1) == '.') {
			return false;
		}

		// If the local string doesnt start and end with quotes
		if ((strpos($local, '"') || strpos($local, ' ')) && (substr($local, 0, 1) != '"' || substr($local, -1, 1) != '"')) {
			return false;
		}

		preg_match(':^([\ \"\w\!\#\$\%\&\'\*\+\-\/\=\?\^\_\`\{\|\}\~\.]{1,64})$:', $local, $local_matches);

		// Check the domain has at least 1 dot in it
		if (strpos($domain, '.') === false) {
			return false;
		}

		if (!empty($local_matches) ) {
			return true;
		} else {
			return false;
		}
	}

	/**
	* Print a message box
	*
	* @param string $desc the description to show in the box
	* @param integer $type the type of message to show
	*/
	function MessageBox($desc, $type=MSG_WARNING)
	{
		// Return a prepared message table row with the appropriate icon
		$iconImage = '';
		$messageBox = '';

		switch ($type) {
			case MSG_ERROR:
				$GLOBALS['Icon'] = 'images/error.gif';
				$GLOBALS['Alt'] = GetLang('Error');
			break;
			case MSG_SUCCESS:
				$GLOBALS['Icon'] = 'images/success.gif';
				$GLOBALS['Alt'] = GetLang('Success');
			break;
			case MSG_INFORMATION:
				$GLOBALS['Icon'] = 'images/info.gif';
				$GLOBALS['Alt'] = GetLang('Information');
			break;
			case MSG_WARNING:
			default:
				$GLOBALS['Icon'] = 'images/warning.gif';
				$GLOBALS['Alt'] = GetLang('Warning');
		}

		$GLOBALS['MsgBox_Message'] = $desc;

		return $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet('MessageBox');
	}

	/**
	* Build a paging navigation. Can be used for searching, lists etc
	*
	* @param string $baselink The link to prepend to each link
	* @param integer $numpages The total number of pages
	* @param integer $current The current page being disaplyed
	* @param string $seperator The string to use to seperate get elements
	* @param bool $replaceLink When true this will treat baselink as a full link and replace variables within. Used for javascript calls.
	*
	* @return string The output of page links
	*/
	function BuildNav($baselink, $numpages, $current, $seperator='&amp;',$replaceLink=false)
	{
		$output = '';
		$pagestoshow = 17;
		
		// Workout the paging navigation
		if ($numpages > 1) {
			$GLOBALS['CurrentPage'] = (int)$current;
			$GLOBALS['TotalPages'] = $numpages;
			
			if (!$replaceLink) {
				$GLOBALS['Link'] = $baselink.$seperator;

				$PagingFirstActive 		= "PagingFirstActive";
				$PagingPrevActive 		= "PagingPrevActive";
				$PagingFirstInactive 	= "PagingFirstInactive";
				$PagingPrevInactive 	= "PagingPrevInactive";
				$PagingCurrentPage 		= "PagingCurrentPage";
				$PagingOtherPage 		= "PagingOtherPage";
				$PagingNextActive 		= "PagingNextActive";
				$PagingLastActive 		= "PagingLastActive";
				$PagingNextInactive 	= "PagingNextInactive";
				$PagingLastInactive 	= "PagingLastInactive";
			} else {
				$GLOBALS['Link'] = $baselink;
				
				$PagingFirstActive 		= "PagingFirstActiveRL";
				$PagingPrevActive 		= "PagingPrevActiveRL";
				$PagingFirstInactive 	= "PagingFirstInactive";
				$PagingPrevInactive 	= "PagingPrevInactive";
				$PagingCurrentPage 		= "PagingCurrentPage";
				$PagingOtherPage 		= "PagingOtherPageRL";
				$PagingNextActive 		= "PagingNextActiveRL";
				$PagingLastActive 		= "PagingLastActiveRL";
				$PagingNextInactive 	= "PagingNextInactive";
				$PagingLastInactive 	= "PagingLastInactive";
			}
			
			$output .= $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet('PagingNumPages');
			
			if ($current > 1) {
				$GLOBALS['PrevPageNumber'] = $current - 1;

				$output .= $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet($PagingFirstActive);
				$output = str_replace("__BUILDNAV_PAGENUMBER__","1",$output);
				
				$output .= $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet($PagingPrevActive);
				$output = str_replace("__BUILDNAV_PAGENUMBER__",$GLOBALS['PrevPageNumber'],$output);
				
			} else {
				$output .= $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet($PagingFirstInactive);
				$output .= $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet($PagingPrevInactive);
			}

			if ($numpages > $pagestoshow) {
				$start_page = $current - (floor($pagestoshow/2));
				if ($start_page < 1) {
					$start_page = 1;
				}

				$end_page = $current + (floor($pagestoshow/2));
				if ($end_page > $numpages) {
					$end_page = $numpages;
				}
				if ($end_page < $pagestoshow) {
					$end_page = $pagestoshow;
				}

				$pagestoshow = ($end_page - $start_page);
				if (($pagestoshow < $pagestoshow) && ($numpages > $pagestoshow)) {
					$start_page = ($end_page - $pagestoshow+1);
				}
			} else {
				$start_page = 1;
				$end_page = $numpages;
			}

			for ($i = $start_page; $i <= $end_page; $i++) {
				$GLOBALS['PageNumber'] = $i;
				if ($i == $current) {
					$output .= $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet($PagingCurrentPage);
				} else {
					$output .= $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet($PagingOtherPage);
					$output = str_replace("__BUILDNAV_PAGENUMBER__",$GLOBALS['PageNumber'],$output);
				}
			}

			if ($current < $numpages) {
				$GLOBALS['PageNumber'] = $current + 1;
				
				$output .= $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet($PagingNextActive);
				$output = str_replace("__BUILDNAV_PAGENUMBER__",$GLOBALS['PageNumber'],$output);
				
				$output .= $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet($PagingLastActive);
				$output = str_replace("__BUILDNAV_PAGENUMBER__",$GLOBALS['TotalPages'],$output);
			} else {
				$output .= $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet($PagingNextInactive);
				$output .= $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet($PagingLastInactive);
			}
		}
		
		return $output;
	}
	
	/**
	* Generate a url to a section of the frontend
	*
	* @param string $type The type of link to generate (i.e. which section it goes to)
	* @param integer $id The id of the page to link to
	* @param string $get Any additional get string to add
	* @param boolean $htmlize Do we run htmlspecialchars on the output before returning ?
	*
	* @return string The url
	*/
	function GetUrl($type, $id=null, $get='', $htmlize=true)
	{
		$url = '';
		switch ($type) {
			case 'category':
				if (($GLOBALS['cleanUrls']) && (!isInlineHelp())) {
					$url = $GLOBALS['pathToKB'].'/categories/';
					if ($id !== null) {
						$url .= $GLOBALS['AKB_CLASS_HELPER']->GetCompleteCategoryPath((int) $id);
					}
				} else {
					$url = $GLOBALS['pathToKB'].'/categories.php';
					if ($id !== null) {
						$url .= '?categoryid='.((int) $id);
					}
					
					if (isInlineHelp()) {
						$url .= "&searchOverride=".(int)$_GET['searchOverride']."&tplHeader=".urlencode($_GET['tplHeader']);
					}					
				}
			break;
			case 'question':
				if (($GLOBALS['cleanUrls']) && (!isInlineHelp())) {
					$url = $GLOBALS['pathToKB'].'/questions/';
					if ($id !== null) {
						$url .= $id.'/';
					}
				} else {
					$url = $GLOBALS['pathToKB'].'/questions.php';
					if ($id !== null) {
						$url .= '?questionid='.((int) $id);
					}
					
					if (isInlineHelp()) {
						$url .= "&searchOverride=".(int)$_GET['searchOverride']."&tplHeader=".urlencode($_GET['tplHeader']);
					}						
				}
			break;
			case 'news':
				if (($GLOBALS['cleanUrls']) && (!isInlineHelp())) {
					$url = $GLOBALS['pathToKB'].'/news/';
					if ($id !== null) {
						$url .= $id.'/';
					}
				} else {
					$url = $GLOBALS['pathToKB'].'/news.php';
					if ($id !== null) {
						$url .= '?newsid='.((int) $id);
					}
				}
			break;
			case 'search':
				if (($GLOBALS['cleanUrls']) && (!isInlineHelp())) {
					$url = $GLOBALS['pathToKB'].'/search/';
					if ($id !== null) {
						$url .= urlencode($id);
					}
				} else {
					$url = $GLOBALS['pathToKB'].'/search.php';
					
					$ns = "?";
					if ($id !== null) {
						$url .= '?q='.urlencode($id);
						$ns = "&";	
					}
					
					if (isInlineHelp()) {
						$url .= $ns."searchOverride=".(int)$_GET['searchOverride']."&tplHeader=".urlencode($_GET['tplHeader']);
					}						
				}
			break;
			case 'rss':
				$url = $GLOBALS['pathToKB'].'/rss.php';
				if ($id !== null) {
					$url .= '?c='.urlencode($id);
				}
			break;
			case 'contact':
				$url = $GLOBALS['pathToKB'].'/contact.php?a=b';
			break;
		}
		if (!empty($get) && !$GLOBALS['cleanUrls']) {
			if ($htmlize) {
				$url .= htmlspecialchars('&'.$get);
			} else {
				$url .= '&'.$get;
			}
		} else if (!empty($get) && $GLOBALS['cleanUrls']) {
			if (substr($get, 0, 5) == 'todo=') {
				$url .= substr($get, 5);
			} else if (substr($get, 0, 5) == 'page=') {
				if ($htmlize) {
					$url .= htmlspecialchars('?'.$get);
				} else {
					$url .= '?'.$get;
				}
			} else if (substr($get, 0, 4) == 'as=1') {
				$url .= '?as=1';
			} else {
				$url .= htmlspecialchars('&'.$get);
			}
		}
		return $url;
	}

	/**
	* Returns the true time in seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)
	*
	* Calling date() with gmtime() as the second parameter is identical to calling
	* gmdate() with time() as the second parameter.
	*/
	function gmtime()
	{
		// Get GM offset. See http://www.php.net/manual/en/function.date.php
		return time() - (int) date('Z');
	}

	/**
	* FrontendAccess
	*
	* Determines if the user has access to the frontend of the site and
	* returns accordingly
	*
	* @return boolean Does the user have access to the frontend ?
	*/
	function FrontendAccess()
	{
		// If either the user or pass on the settings page is blank then let
		// them in
		if (empty($GLOBALS['frontendUser'])
			|| empty($GLOBALS['frontendPass'])) {
			return true;
		}

		// If the user has already authenticated, cool let them in
		if (isset($_SESSION['frontendUser']) && isset($_SESSION['frontendPass']) && $_SESSION['frontendUser'] == $GLOBALS['frontendUser'] && $_SESSION['frontendPass'] == $GLOBALS['frontendPass']) {
			return true;
		}

		// If the user is trying to authenticate and suceeds, let them in
		if (isset($_POST['frontendUser']) && isset($_POST['frontendPass']) && $_POST['frontendUser'] == $GLOBALS['frontendUser'] && $_POST['frontendPass'] == $GLOBALS['frontendPass']) {
			$_SESSION['frontendUser'] = $GLOBALS['frontendUser'];
			$_SESSION['frontendPass'] = $GLOBALS['frontendPass'];
			if (isset($_POST['frontendRemember'])
				&& isset($_POST['frontendRemember']) == 1) {
				// Allow the user to be remembered for 2 weeks (i.e. 14 days)
				$cookielength = time()+60*60*24*14;
				setcookie($GLOBALS['cookiePrefix'].'akb_f_u', $GLOBALS['frontendUser'], $cookielength);
				setcookie($GLOBALS['cookiePrefix'].'akb_f_p', $GLOBALS['frontendPass'], $cookielength);
			}
			return true;
		}

		// If they clicked the remember me option in the past
		if (isset($_COOKIE[$GLOBALS['cookiePrefix'].'akb_f_u']) && isset($_COOKIE[$GLOBALS['cookiePrefix'].'akb_f_p']) && $_COOKIE[$GLOBALS['cookiePrefix'].'akb_f_u'] == $GLOBALS['frontendUser'] && $_COOKIE[$GLOBALS['cookiePrefix'].'akb_f_p'] == $GLOBALS['frontendPass']) {
			$_SESSION['frontendUser'] = $GLOBALS['frontendUser']; $_SESSION['frontendPass'] = $GLOBALS['frontendPass'];
			return true;
		}

		// The site is password protected and they havn't authorised so fail
		return false;
	}

	/**
	* CheckIntVars
	* This goes through the array passed in and strips out any non-numeric characters. This can then be used safely for implodes for searching particular listid's or subscriberid's without worrying about sql injection.
	* create_function creates a dynamic function so we don't have another function to call inside this one.
	* Quoted numbers such as '2' or "11" will get returned without the quotes as per is_numeric functionality.
	*
	* <b>Example</b>
	* <code>
	* $vals = array(1,'12', 'f', "string");
	* $vals = CheckIntVars($vals);
	* </code>
	* This will become:
	* <code>
	* $vals = array(1, 12);
	* </code>
	*
	* @param Array $array_to_check Array of values to check and make sure they are integers.
	*
	* @return Array Array of values which are numbers only. All non-numeric characters or strings are removed.
	*/
	function CheckIntVars($array_to_check=array())
	{
		if (!is_array($array_to_check)) {
			return array();
		}
		$new_func = create_function('$x', 'return is_numeric($x);');
		return array_filter($array_to_check, $new_func);
	}

	if (!function_exists('html_entity_decode')) {
		/**
		* html_entity_decode
		* Convert all HTML entities to their applicable characters
		*
		* @param string $string The string to convert
		*
		* @return string The converted string
		*/
		function html_entity_decode($string)
		{
			// replace numeric entities
			$string = preg_replace('~&#x([0-9a-f]+);~ei', 'chr(hexdec("\\1"))', $string);
			$string = preg_replace('~&#([0-9]+);~e', 'chr(\\1)', $string);
			// replace literal entities
			$trans_tbl = get_html_translation_table(HTML_ENTITIES);
			$trans_tbl = array_flip($trans_tbl);
			return strtr($string, $trans_tbl);
		}
	}

	/**
	* GetLang
	*
	* Return a language string
	*
	* @param string $var The name of the language string to return
	*
	* @return string The language string or an empty string if its not defined
	*/
	function GetLang($var)
	{
		if (isset($GLOBALS['AKB_LANG'][$var])) {
			return $GLOBALS['AKB_LANG'][$var];
		} else {
			return '';
		}
	}

	/**
	* Create options for a character set dropdown
	*
	* @param string $set The currently selected character set
	*
	* @return string The html to create the options
	*/
	function GetCharsetOptions($set = '')
	{
		if ($set == '' || empty($set)) {
			$set = 'iso-8859-1';
		}
		$out = '';

		$charset['value'][] = 'iso-8859-1';
		$charset['name'][] = 'Western Alphabet (ISO-8859-1)';

		$charset['value'][] = 'utf-8';
		$charset['name'][] = 'Universal Alphabet (UTF-8)';

		foreach ($charset['name'] as $key=>$val) {
			$out .= "<option value='".$charset['value'][$key]."' ";
			if ($set == $charset['value'][$key]) {
				$out .= "selected";
				$set = "blah";
			}
			$out .= ">".$val."</option>\n";
		}
		return $out;
	}

	/**
	* Colourise the keywords in a string to make it easier to see the relevant parts of the text
	*
	* @param string $str The string to colourise
	* @param array $words The array of words to colourise
	*
	* @return string The colourised string
	*/
	function ReplaceString($str, $arrWords, $callback)
	{
		// If we don't have an array of words or the array is empty
		// then we don't need to do anything
		if (!is_array($arrWords) || empty($arrWords)) {
			return $str;
		}

		$output = $str;

		if (!empty($arrWords) && is_array($arrWords)) {
			// We do two loops because otherwise we have to deal with the
			// case where we have a glossary term which is one of the words
			// in a multi word glossary term. Doing it this way avoids that
			// problem easily

			// Because doing a preg_replace is expensive, lets check to make
			// sure there is something that looks like a glossary word in
			// the answer before we proceed
			
			for ($i = 0; $i < sizeof($arrWords); $i++) {
				$matches = array();
				$regex = '#(?![^<]*?>)(?!<a[^>]*>)\b'.preg_quote($arrWords[$i]['word'], '#').'\b(?![^<]*</a>)#si';
				preg_match($regex, $output, $matches);
				if (!empty($matches)) {
					$arrWords[$i]['original'] = $matches[0];
					$output = preg_replace($regex, $arrWords[$i]['token'], $output, 1);
				}
			}

			/*
			// This loop is here for replacing glossary terms on multi-byte
			// character systems like korean, chinese and japanese
			for ($i = 0; $i < sizeof($arrWords); $i++) {
				$arrWords[$i]['original'] = $arrWords[$i]['word'];
				$output = str_replace($arrWords[$i]['word'], $arrWords[$i]['token'], $output);
			}
			*/

			// Replace the tokens with the popups
			for ($i = 0; $i < sizeof($arrWords); $i++) {
				if (!isset($arrWords[$i]['original']) || empty($arrWords[$i]['original'])) {
					continue;
				}
				$result = call_user_func($callback, $arrWords[$i]);

				// Replace token with the popup
				$output = str_replace($arrWords[$i]['token'], $result, $output);
			}

		}

		$output = str_replace('%%','&#37;&#37;',$output);

		return $output;

	}

	function GlossaryPopupCallback($arr)
	{
		$word = $arr['original'];
		$desc = $arr['desc'];
		$desc = str_replace(array("\r", "\n", '"'), array('', '<br />', '&quot;'), $desc);
		$desc = addslashes($desc);

		$GLOBALS['Word'] = $word;
		$GLOBALS['Description'] = $desc;
		$popup = $GLOBALS['AKB_CLASS_TEMPLATE']->GetSnippet('GlossaryWordPopup');
		$popup = str_replace(array("\r", "\n"), '', $popup);

		return $popup;
	}

	function SearchTermCallback($arr)
	{
		static $seen = Array();

		if (isset($seen[strtolower($arr['original'])])) {
			$currentWordNum = $seen[strtolower($arr['original'])];
		} else {
			$seen[strtolower($arr['original'])] = count($seen)+1;
			$currentWordNum = $seen[strtolower($arr['original'])];
		}

		$color = ($currentWordNum % 4) + 1;
		$output = '<b class="res_word res_word_'.($color).'">'.$arr['original'].'</b>';
		return $output;
	}

	/**
	* Get a list of letters for for address book style shortcuts to results
	*
	* @return array
	*/
	function GetAlphaList()
	{
		return array_map('trim', explode(',', GetLang('AlphaLetters')));
	}
	
	/**
	 * CheckZero
	 * This makes sure that a number is always 2 digits or more. So if the input is 3
	 * it will change it to 03. If its already 2 digits or more, it will leave it as
	 * it is.
	 *
	 * @param mixed $input Can be an integer or a string
	 * @return mixed If the zero is added, it becomes a string, otherwise it is what
	 * ever $input was.
	 */
	function CheckZero($input){
		if(strlen($input) < 2){
			$input = (string)$input;
			$input = (string)'0'.$input;
		}
		return $input;
	}
	
	
	function SendServerInfo($installtype=0,$prev_version=0,$new_version=0){
		# parse the PHP Info to get module information
		$phpinfo = @ParsePHPModules();

		# check php info
		$info['php'] = phpversion();

		#check the mysql version
		$info['mysql'] = $phpinfo['mysql']['Client API version'];

		# check for sqlite
		$info['sqlite'] = (isset($phpinfo['sqlite'])) ? $phpinfo['sqlite']['SQLite Library'] : '0';

		# check for mbstring
		$info['mbstring'] = (isset($phpinfo['mbstring'])) ? '1' : '0';

		# curl check
		$info['curl'] = (function_exists('curl_init')) ? '1' : '0';

		# curl check
		$info['exif'] = (isset($phpinfo['exif'])) ? '1' : '0';

		# check their charset being used
		$info['alcharset'] = $GLOBALS['charset'];

		# check for iconv, also check the lib version
		$info['iconv'] = (function_exists('iconv')) ? '1' : '0';
		if(isset($phpinfo['iconv'])){
			$info['iconvlib'] = $phpinfo['iconv']["iconv implementation"] . '|' . $phpinfo['iconv']["iconv library version"];
		}else{
			$info['iconvlib'] = '0';
		}

		# check for GD, return the version if so
		if(isset($phpinfo['gd'])){
			$info['gd'] = $phpinfo['gd']["GD Version"];
		}else{
			$info['gd'] = '0';
		}

		# check cgi mode
		$sapi_type = php_sapi_name();
		$info['cgimode'] = (strpos($sapi_type, 'cgi') !== false) ? '1' : '0';

		$info['serversoftware']		= $_SERVER["SERVER_SOFTWARE"];
		$info['allow_fopen_url']	= (!(bool)ini_get('safe_mode') && ini_get('allow_url_fopen'));

		$info['safe_mode']	= ((bool)ini_get('safe_mode')) ? '1' : '0';
		$info['ftp']		= (function_exists('ftp_login')) ? '1' : '0';
		$info['postsize']	= ini_get('post_max_size');
		$info['uploadsize'] = ini_get('upload_max_filesize');
		$info['imap']		= (function_exists('imap_open')) ? '1' : '0';
		$info['doccorrect'] = (DocrootRight()) ? '1': '0';
		$info['zlib'] = (isset($phpinfo['zlib'])) ? '1' : '0';
		$info['installtype'] = $installtype;	//0 = new, 1 = upgrade
		$info['prev'] = $prev_version;
		$info['new']  = $new_version;
		$info['app']  = PRODUCT_ID;

		require_once('../lib/remoteopener.php');

		$opener = new connect_remote();
		$string = '';

		foreach($info as $key=>$value){
			$string .= $key. '=' .urlencode($value).'&';
		}

		/* We need a unique ID for the host
		   if we sha1 it here, the ID will always be the same
		   but no one will know what the host name is
		   so it preserves the privacy of the user
		   sha1() is the best for this, but if its not aval, md5() is
		   almost as good.
		*/

		if($_SERVER['HTTP_HOST'] == "localhost"){
			$_id = $_SERVER['HTTP_HOST']. time();
		}else{
			$_id = $_SERVER['HTTP_HOST'];
		}

		if(function_exists('sha1')){
			$string .= 'id='. sha1($_id);
		}else{
			$string .= 'id='. md5($_id);
		}

		if(@function_exists("curl_init") || (int)@ini_get("allow_url_fopen") != 0){
			@$opener->Open('http://server-stats.info/stats.php?'.$string, $tplData);
		}else{
			$GLOBALS['InfoImage'] = "<img src='http://server-stats.info/blank.gif?".$string."' />";
		}
	}

	/**
	 * ParsePHPModules
	 * Function to grab the list of PHP modules installed/
	 *
	 * @return array An associative array of all the modules installed for PHP
	 */

	function ParsePHPModules() {
		ob_start();
		phpinfo(INFO_MODULES);
		$s = ob_get_contents();
		ob_end_clean();

		$s = strip_tags($s,'<h2><th><td>');
		$s = preg_replace('/<th[^>]*>([^<]+)<\/th>/',"<info>\\1</info>",$s);
		$s = preg_replace('/<td[^>]*>([^<]+)<\/td>/',"<info>\\1</info>",$s);
		$vTmp = preg_split('/(<h2[^>]*>[^<]+<\/h2>)/',$s,-1,PREG_SPLIT_DELIM_CAPTURE);
		$vModules = array();
		for ($i=1;$i<count($vTmp);$i++) {
			if (preg_match('/<h2[^>]*>([^<]+)<\/h2>/',$vTmp[$i],$vMat)) {
				$vName = trim($vMat[1]);
				$vTmp2 = explode("\n",$vTmp[$i+1]);
				foreach ($vTmp2 AS $vOne) {
					$vPat = '<info>([^<]+)<\/info>';
					$vPat3 = "/$vPat\s*$vPat\s*$vPat/";
					$vPat2 = "/$vPat\s*$vPat/";
					if (preg_match($vPat3,$vOne,$vMat)) { // 3cols
						$vModules[$vName][trim($vMat[1])] = array(trim($vMat[2]),trim($vMat[3]));
					} elseif (preg_match($vPat2,$vOne,$vMat)) { // 2cols
						$vModules[$vName][trim($vMat[1])] = trim($vMat[2]);
					}
				}
			}
		}
		return $vModules;
	}

	function DocrootRight()
	{
		if (!isset($_SERVER['DOCUMENT_ROOT'])) return false;
		if ($_SERVER['DOCUMENT_ROOT']=='') return false;
		$s = str_replace('\\','/', $_SERVER['DOCUMENT_ROOT']);
		$f = str_replace('\\','/', __FILE__);
		if (startequals($f, $s)) return true;
		return false;
	}
	
	function startequals($haystack,$needle)
	{
		$a = strpos(strtolower($haystack),strtolower($needle));
		if (!is_numeric($a)) return false;
		if ($a==0) return true;
		return false;
	}
	
	function setEmailVars(&$emailObj) {
	
		//We use PHP settings. Do nothing.
		if ($GLOBALS['smtpDefault']) {
			return;
		}
		
		if ($GLOBALS['smtpServer'] != "") {
			$emailObj->SMTPServer = $GLOBALS['smtpServer'];
		}
		
		if ($GLOBALS['smtpUsername'] != "") {
			$emailObj->SMTPUsername = $GLOBALS['smtpUsername'];
		}
		
		if ($GLOBALS['smtpPassword'] != "") {
			$emailObj->SMTPPassword = $GLOBALS['smtpPassword'];
		}
		
		if ($GLOBALS['smtpPort'] != "") {
			$emailObj->SMTPPort = $GLOBALS['smtpPort'];
		}
	}
	
	function isInlineHelp() {
		return ((isset($_REQUEST['searchOverride'])) && (isset($_REQUEST['tplHeader'])));
	}

	/**
	* Draw the Interspire Knowledge Manager logo. The logo file cannot be modified
	* in any way, as this will void your license agreement with Interspire
	*/
	function DrawLogo()
	{
		$fp = fopen(dirname(__FILE__) . "/../admin/images/app.dat", "rb");
		$logo = '';

		while (!feof($fp)) {
			$logo .= fgets($fp, 4096);
		}

		fclose($fp);
		ob_end_clean();
		header("Content-Type: image/jpeg");
		echo $logo;
		die();
	}
	
	/**
	* GenerateXML
	* Generate the xml file for Articles per Users
	* 
	* @param String $TargetData The flag of which stats' XML that are to be generated
	* @param Integer $from The Timestamp of the start date to be searched
	* @param Integer $to The Timestamp of the end date to be searched
	* 
	* 
	*/
	function GenerateXML ($TargetData, $from, $to) {
		$whereClause = '';
		switch ($TargetData) {
			case 'statsUserPerArticlesXml':
				$from = date('Y-m-d 00:00:00', $from);
				$to = date('Y-m-d 23:59:00', $to);
				$whereClause .= "AND (q.lastupdated >= '$from' and q.lastupdated <= '$to' OR q.lastupdated is null)";
				$query = 
				"SELECT u.userid, u.firstname, u.lastname, u.username, count(q.userid) as total "
				." FROM ".$GLOBALS['tablePrefix']."users u "
				." LEFT JOIN ".$GLOBALS['tablePrefix']."questions q on q.userid = u.userid"
				." WHERE 1=1 "
				."$whereClause "
				." GROUP BY u.userid, u.firstname, u.lastname, u.username"
				 ." ORDER BY total DESC, u.firstname, u.lastname, u.username"
				;
			
				$result = $GLOBALS['AKB_DB']->Query($query);
				// Build the Graph Data
				$barColor = array(
				'#5d478b', 
				'#708090', 
				'#191970', 
				'#006400', 
				'#8b4513', 
				'#b22222', 
				'#b03060', 
				'#9370db', 
				'#8b8989', 
				'#8b795e', 
				'#483d8b', 
				'#8b7d7b', 
				'#27408b', 
				'#00868b', 
				'#2e8b57', 
				'#cd2626', 
				'#8b7b8b', 
				'#e6e6fa', 
				'#2f4f4f', 
				'#556b2f'
				);
				$xml = '<?xml version="1.0" encoding="'.$GLOBALS['charset'].'"?>';
				$xml .= '<chart>';
				$xmlSeries = '	<series>';
				$xmlGraphs = '  <graphs>';
				$xmlGraphs .= '    <graph gid="0" color="#9FCDFF">';
				
				// get the series and graphs
				$xmlCounter = 0;
				while ($row = $GLOBALS['AKB_DB']->Fetch($result)) {
					if (trim($row['firstname']) != '' || trim($row['lastname']) != '') {
						$xmlSeries .= '<value xid="'.$xmlCounter.'">' . $row['firstname'].' '.$row['lastname'] . '</value>';
					} else {
						$xmlSeries .= '<value xid="'.$xmlCounter.'">' . $row['username'] . '</value>';
					}
					$xmlGraphs .= '<value xid="'.$xmlCounter.'" color="'.$barColor[$xmlCounter].'">' . $row['total'] . '</value>';
					$xmlCounter++;
				}
				$xmlSeries .= '  </series>';
				$xmlGraphs .= '  	</graph>';
				$xmlGraphs .= '  </graphs>';
				
				$xml .= $xmlSeries;
				$xml .= $xmlGraphs;
				$xml .= '</chart>';
				echo $xml;
				break;
			
			default:
			echo '';
			break;
		}
	}
	
	/**
	* Behaves like the unix which command
	* It checks the path in order for which version of $binary to run
	*
	* @param string $binary The name of a binary
	*
	* @return string The full path to the binary or an empty string if it couldn't be found
	*/
	function Which($binary)
	{
		// If the binary has the / or \ in it then skip it
		if (strpos($binary, DIRECTORY_SEPARATOR) !== false) {
			return '';
		}
		$path = null;
		$allPath = '';
		$dirs_to_check = array(dirname(__FILE__).'/search/plugins');
		
		if (ini_get('safe_mode')) {
			// if safe mode is on the path is in the ini setting safe_mode_exec_dir
			$_SERVER['safe_mode_path'] = ini_get('safe_mode_exec_dir');
			$path = 'safe_mode_path';
			$dirs_to_check = array_merge($dirs_to_check, explode(PATH_SEPARATOR, $_SERVER[$path]));
		} else if (isset($_SERVER['PATH']) && $_SERVER['PATH'] != '') {
			// On unix the env var is PATH
			$path = 'PATH';
			$dirs_to_check = array_merge($dirs_to_check, explode(PATH_SEPARATOR, $_SERVER[$path]));
		} else if (isset($_SERVER['Path']) && $_SERVER['Path'] != '') {
			// On windows under IIS the env var is Path
			$path = 'Path';
			$dirs_to_check = array_merge($dirs_to_check, explode(PATH_SEPARATOR, $_SERVER[$path]));
		} else if ($allPath = getenv('Path')) {
			$dirs_to_check = array_merge($dirs_to_check, explode(PATH_SEPARATOR, $allPath));
		}

		$open_basedirs = array();
		if (ini_get('open_basedir')) {
			$open_basedirs = explode(PATH_SEPARATOR, ini_get('open_basedir'));
		}

		foreach ($dirs_to_check as $dir) {
			if (substr($dir, -1) == DIRECTORY_SEPARATOR) {
				$dir = substr($dir, 0, -1);
			}
			$can_check = true;
			if (!empty($open_basedirs)) {
				$can_check = false;
				foreach ($open_basedirs as $restricted_dir) {
					if (trim($restricted_dir) === '') {
						continue;
					}
					if (strpos($dir, $restricted_dir) === 0) {
						$can_check = true;
					}
				}
			}

			if ($can_check && is_dir($dir) && is_file($dir.DIRECTORY_SEPARATOR.$binary)) {
				return $dir.DIRECTORY_SEPARATOR.$binary;
			}
		}
		return '';
	}
	
	function pageLoad() {
		$auth = new AKB_AUTH();
		$login = $auth->IsLoggedIn();
		if ($login) {
			$query = "SELECT COUNT(userid) as tot FROM %susers WHERE username = '%s' AND sessionid='%s' ";
			$query = sprintf($query, $GLOBALS['tablePrefix'], $_SESSION['user']->username, $_SESSION['user']->sessionid);
			$total = $GLOBALS['AKB_DB']->FetchOne($query);
			if ($total != 1) {
				unset($_SESSION['user']);
	
				// Set the cookies to a time in the past
				setcookie($GLOBALS['cookiePrefix'].'RememberMe', '', time() - 3600*24*365);
				setcookie($GLOBALS['cookiePrefix'].'RememberUser', '', time() - 3600*24*365);
				setcookie($GLOBALS['cookiePrefix'].'RememberPass', '', time() - 3600*24*365);
	
				if (isset($_COOKIE[session_name()])) {
					setcookie(session_name(), '', time()-42000, '/');
				}
				session_destroy();
				return false;
			}
		}
		return true;
	}

	/**
		* Get a page given a $url
		* If $lastmod is given and > 0 AND we can use curl then only fetch the
		* page if it has been updated since $lastmod. Also
		* $this->http_response_code is set to the http response code from the
		* fetch if using curl
		*
		* @param string $url the full url to fetch including http://
		* @param int $lastmod the number of seconds since epoch (unix timestamp)
		* when the page was last known to be checked
		*
		* @return string The contents of the page or an empty string if the page
		* has not beed modified since $lastmod
		*/
	function getPage($url, $lastmod = 0)
	{
		if (!$url) {
			$pageData = false;
			return $pageData;
		}
	
		if (function_exists("curl_init")) {
			$ch = curl_init();
			curl_setopt($ch, CURLOPT_URL, $url);
			if (!ini_get('safe_mode') && ini_get('open_basedir') === '') {
				curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
			}
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
			curl_setopt($ch, CURLOPT_FAILONERROR, true);
			curl_setopt($ch, CURLOPT_TIMEOUT, 30);
			curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
//			curl_setopt($ch, CURLOPT_USERAGENT, sprintf(GetLang('crawlerUserAgent'), FF_VERSION));
			if ((int)$lastmod > 0) {
				if (defined('CURLOPT_TIMEVALUE') && defined('CURLOPT_TIMECONDITION') && defined('CURL_TIMECOND_IFMODSINCE')) {
					curl_setopt($ch, CURLOPT_TIMEVALUE, $lastmod);
					curl_setopt($ch, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
				}
			}
	
			$pageData = curl_exec($ch);
	
			$http_response_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
			curl_close($ch);
	
			return $pageData;
		}
	
		$fp = false;
		if (!@$fp = fopen($url, "rb")) {
			$pageData = false;
			return $pageData;
		}
	
		// Grab the files content
		$pageData = "";
	
		while (!feof($fp)) {
			$pageData .= fgets($fp, 4096);
		}
	
		fclose($fp);
	
		return $pageData;
	}
	
	function stripPluginHeader ($content, $filename = '') {
		$tmpPos = 0;
		if ($tmpPos = strpos($content, "Created with pptHtml")) {
			$content = substr($content, 0, $tmpPos);
		}
		if ($tmpPos = strpos($content, "Pdf_Plugin")) {
			$content = substr($content, 0, $tmpPos);
		}
		if (strstr ($content, '.tmp')) {
			$content = str_replace('.tmp', '', strstr ($content, '.tmp'));
		}
		$tmpPos = strpos($content, "PPT");
		if ($tmpPos) {
			$content = substr($content, $tmpPos+9);
		}
		return $content;
	}
	
	function phpClone($object) {
		if (version_compare(phpversion(), '5.0') < 0) {
			return $object;
		} else {
			return @clone($object);
		}
	}
	
	function validUrl() {
		$akbHelper	= new AKB_HELPER;
		return 	$akbHelper->validUrl($akbHelper->get1n());
	
	}
	
	function encodeWorkflowStatus($var) {
		$arr = array(
			trim(GetLang('WorkflowApproved')) => WF_STATUS_APPROVED ,
			trim(GetLang('WorkflowAutoApproved')) => WF_STATUS_AUTO_APPROVED,
			trim(GetLang('WorkflowDisapproved')) => WF_STATUS_DISAPPROVED,
			trim(GetLang('WorkflowRepending')) => WF_STATUS_REPENDING,
		);
		
		if (isset($arr[$var])) {
			return $arr[$var];
		}
		return '';
	}
	
	function decodeWorkflowStatus($var) {
		$arr = array(
			WF_STATUS_APPROVED => trim(GetLang('WorkflowApproved')),
			WF_STATUS_AUTO_APPROVED => trim(GetLang('WorkflowAutoApproved')),
			WF_STATUS_DISAPPROVED => trim(GetLang('WorkflowDisapproved')),
			WF_STATUS_PENDING => trim(GetLang('WorkflowPending')),
			WF_STATUS_REPENDING => trim(GetLang('WorkflowRepending'))
		);
		
		if (isset($arr[$var])) {
			return $arr[$var];
		}
		return '';
	}
	
	/**
	*	Post to a remote file and return the response.
	*	Vars should be passed in URL format, i.e. x=1&y=2&z=3
	*/
	function PostToRemoteFileAndGetResponse($Path, $Vars="", $timeout=10)
	{

		$result = null;

		if(function_exists("curl_exec")) {
			$safemode = @ini_get('safemode');
			// Use CURL if it's available
			$ch = curl_init($Path);

			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
			if (!$safemode && ini_get('open_basedir') == '') {
				@curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
			}
			if($timeout > 0 && $timeout !== false) {
				curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
			}

			// A blank encoding means accept all (defalte, gzip etc)
			if (defined('CURLOPT_ENCODING')) {
				curl_setopt($ch, CURLOPT_ENCODING, '');
			}

			if($Vars != "") {
				curl_setopt($ch, CURLOPT_POST, 1);
				curl_setopt($ch, CURLOPT_POSTFIELDS, $Vars);
			}
			$result = curl_exec($ch);
		}
		else {
			// Use fsockopen instead
			$Path = @parse_url($Path);
			if(!isset($Path['host']) || $Path['host'] == '') {
				return null;
			}
			if(!isset($Path['port'])) {
				$Path['port'] = 80;
			}
			if(!isset($Path['path'])) {
				$Path['path'] = '/';
			}
			if(isset($Path['query'])) {
				$Path['path'] .= "?".$Path['query'];
			}

			if(isset($Path['scheme']) && strtolower($Path['scheme']) == 'https') {
				$socketHost = 'ssl://'.$Path['host'];
				$Path['port'] = 443;
			}
			else {
				$socketHost = $Path['host'];
			}

			$fp = @fsockopen($Path['host'], $Path['port'], $errorNo, $error, 10);
			if($timeout > 0 && $timeout !== false) {
				@stream_set_timeout($fp, 10);
			}
			if(!$fp) {
				return null;
			}

			$headers = array();

			// If we have one or more variables, perform a post request
			if($Vars != '') {
				$headers[] = "POST ".$Path['path']." HTTP/1.0";
				$headers[] = "Content-Length: ".strlen($Vars);
				$headers[] = "Content-Type: application/x-www-form-urlencoded";
			}
			// Otherwise, let's get.
			else {
				$headers[] = "GET ".$Path['path']." HTTP/1.0";
			}
			$headers[] = "Host: ".$Path['host'];
			$headers[] = "Connection: Close";

			if($Vars != '') {
				$headers[] = $Vars; // Extra CRLF to indicate the start of the data transmission
			}

			$headers[] = "\r\n";

			if(!fwrite($fp, implode("\r\n", $headers))) {
				return false;
			}
			while(!feof($fp)) {
				$result .= @fgets($fp, 12800);
			}
			@fclose($fp);

			// Strip off the headers. Content starts at a double CRLF.
			$result = explode("\r\n\r\n", $result, 2);
			$result = $result[1];
		}
		return $result;
	}
	
	function XmlShowError ($message, $errors, $statusCode='ERROR') {
		header("Content-Type: text/xml");
		echo '<'.'?xml version="1.0" encoding="'.$GLOBALS["charset"].'" ?'.">\n";
		echo "<response>\n";
		echo "  <status>$statusCode</status>\n";
		echo "  <message>".htmlspecialchars($message, ENT_QUOTES, $GLOBALS["charset"])."</message>\n";
		echo "  <errors>\n";
		foreach($errors as $error) {
			$error['message'] = strip_tags($error['message']);
			if(isset($error['extra']) && $error['extra'] != '') {
				$extra = " extra=\"".$error['extra']."\"";
			}
			else {
				$extra = '';
			}
			echo "      <error code=\"".$error['code']."\"".$extra.">".htmlspecialchars($error['message'], ENT_QUOTES, $GLOBALS["charset"])."</error>\n";
		}
		echo "  </errors>\n";
		echo "</response>";
	}
	
	function XmlGetRequest () {
		$request = @file_get_contents("php://input");
		if(!$request) {
			exit;
		}
		
		$request = @simplexml_load_string($request);
		if(!is_object($request)) {
			$errors = array(
			0 => array(
			'code' => 'invalidRequest',
			'message' => ''
			)
			);
			XmlShowError('The request contained invalid XML.', $errors);
			return false;
		}
		return $request;
	}
	
	function XmlShowResponse($message, $params = false, $statusCode='OK') {
		header("Content-Type: text/xml");
		echo '<'.'?xml version="1.0" encoding="'.$GLOBALS["charset"].'" ?'.">\n";
		echo "<response>\n";
		echo "  <status>$statusCode</status>\n";
		echo "  <message>".htmlspecialchars($message, ENT_QUOTES, $GLOBALS["charset"])."</message>\n";
		if ($params && is_array($params) && sizeof($params)) {
			PrintXmlParams($params);
		}
		echo "</response>";
	}
	
	function PrintXmlParams ($response, $space=' ') {
		if (is_array($response)) {
			foreach ($response as $k=>$v) {
				echo (is_numeric($k))?'':"$space<$k>" . "\n";
				if (is_array($v)) {
					PrintXmlParams($v,$space.' ');
				} else {
					echo "$space   $v\n";
				}
				echo (is_numeric($k))?'':"$space</$k>" . "\n";
			}
		}
	}
	
	function generateTokenCode ($str) {
		return sha1($str) . md5(microtime()) . sha1(str_shuffle($str));
	}
	
	/**
	 * Fetch the IP address of the current user.
	 *
	 * @return string The IP address.
	 */
	function GetIPAdd()
	{
		if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
			if(preg_match_all("#[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}#s", $_SERVER['HTTP_X_FORWARDED_FOR'], $addresses)) {
				foreach($addresses[0] as $key => $val) {
					if(!preg_match("#^(10|172\.16|192\.168)\.#", $val)) {
						$ip = $val;
						break;
					}
				}
			}
		}

		if(!isset($ip)) {
			if(isset($_SERVER['HTTP_CLIENT_IP'])) {
				$ip = $_SERVER['HTTP_CLIENT_IP'];
			}
			else {
				$ip = $_SERVER['REMOTE_ADDR'];
			}
		}
		$ip = preg_replace("#([^.0-9 ]*)#", "", $ip);
		return $ip;
	}
	
	/**
	* IsLoggedIn
	*
	* Check if a user is logged in or not
	*
	* @return boolean
	*/
	function IsLoggedIn() {
		$isLoggedIn = (isset($_SESSION['user']) && $_SESSION['user']->userid > 0);
		return $isLoggedIn;
	}
	
	function getShowDisapprovedArticleString($condition = 'OR', $prefix = '', $operator = '=') {
		if (isset($GLOBALS['showDisapprovedArticles']) && $GLOBALS['showDisapprovedArticles']) {
			return " $condition $prefix"."workflowstatus $operator '".WF_STATUS_DISAPPROVED."' ";
		}
		return '';
	}
	function getShowDisapprovedArticleArray() {
		$validStatus = array(WF_STATUS_REPENDING);
		if (isset($GLOBALS['showDisapprovedArticles']) && $GLOBALS['showDisapprovedArticles']) {
			$validStatus[] = WF_STATUS_DISAPPROVED;
		}
		return $validStatus;
	}
	
?>